# -*- coding: utf-8 -*-
from os import path
from hashlib import md5
from datetime import date

from django.db import models
from django.db import IntegrityError
from django.core.cache import cache
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from django.utils.encoding import smart_str
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
User = get_user_model()
from django.utils.timezone import now
from django.utils.translation.trans_real import ugettext

# from django.template.defaultfilters import slugify
from autoslug import AutoSlugField

from yummy import conf
from yummy import managers

try:
    from ella.core.cache.fields import CachedForeignKey
except ImportError:
    CachedForeignKey = models.ForeignKey


class CookingType(models.Model):

    name = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=64, unique=True)
    slug = AutoSlugField(u'Слуг', max_length=64, populate_from='name',
                         unique_with=('name'),
                         slugify=lambda value: value.replace(' ','-'))
    description = models.TextField(u'Описание', blank=True)

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = u'Тип рецепта'
        verbose_name_plural = u'Типы рецептов'


class TargetGroup(models.Model):

    name = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=64, unique=True)
    slug = AutoSlugField(u'Слуг', max_length=64, populate_from='name',
                         unique_with=('name'),
                         slugify=lambda value: value.replace(' ','-'))
    description = models.TextField(u'Описание', blank=True)

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = u'Целевая группа'
        verbose_name_plural = u'Целевые группы'

    '''def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        return super(TargetGroup, self).save(*args, **kwargs)'''

    def get_absolute_url(self):
        return reverse('yummy:targetgroup_detail', args=(self.slug,))


class Cuisine(models.Model):

    name = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=64, unique=True)
    slug = AutoSlugField(u'Слуг', max_length=64, populate_from='name',
                         unique_with=('name'),
                         slugify=lambda value: value.replace(' ','-'))
    description = models.TextField(u'Описание', blank=True)

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = u'Национальная кухня'
        verbose_name_plural = u'Национальные кухни'

    '''def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        return super(Cuisine, self).save(*args, **kwargs)'''

    def get_absolute_url(self):
        return reverse('yummy:cuisine_detail', args=(self.slug,))


class IngredientGroup(models.Model):

    name = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=128, unique=True)
    slug = AutoSlugField(u'Слуг', max_length=64, populate_from='name',
                         unique_with=('name'),
                         slugify=lambda value: value.replace(' ','-'))

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = 'Группа ингредиентов'
        verbose_name_plural = u'Группы ингредиентов'

    '''def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        return super(IngredientGroup, self).save(*args, **kwargs)'''


class Ingredient(models.Model):

    group = CachedForeignKey(IngredientGroup, verbose_name=u'Группа ингредиентов', null=True, blank=True)
    name = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=64, unique=True)
    slug = AutoSlugField(u'Слуг', max_length=64, populate_from='name',
                         unique_with=('name', 'group'),
                         slugify=lambda value: value.replace(' ','-'))
    genitive = models.CharField(u'Родительный падеж', max_length=128, blank=True)
    default_unit = models.PositiveSmallIntegerField(choices=conf.UNIT_CHOICES,
        verbose_name=u'Единица измерения', null=True, blank=True)

    ndb_no = models.IntegerField(_('NDB id number'), blank=True, null=True)
    is_approved = models.BooleanField(u'Утвержденн', default=True, db_index=True)

    objects = managers.IngredientManager()

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = u'Ингредиент'
        verbose_name_plural = u'Ингредиенты'

    def save(self, *args, **kwargs):
        # if not self.slug:
            # self.slug = slugify(self.name)
        super(Ingredient, self).save(*args, **kwargs)

        Ingredient.objects.get_names_list(recache=True)

    def get_absolute_url(self):
        return reverse('yummy:ingredient_detail', args=(self.slug,))


'''def upload_to(instance, filename):
    name, ext = path.splitext(filename)
    to_hash = '|'.join((name, now().strftime('%Y-%m-%d %H:%M:%S'), smart_str(instance.owner)))
    h = md5(to_hash).hexdigest()

    return path.join(
        "yummy",
        h[:2],
        h[2:4],
        h + ext.lower()
    )'''

from photologue.models import Photo as PhPhoto
from photologue.models import PhotoSize
class Photo(PhPhoto):

    is_redaction = models.BooleanField(default=False, editable=False)
    created = models.DateTimeField(editable=False)
    owner = CachedForeignKey(User, verbose_name=u'Гурман', editable=False)
    size =  CachedForeignKey(PhotoSize,
        default=conf.RECIPESIZE, verbose_name=u'Размер фотографии')  # надо?

    def __unicode__(self):
        return unicode(self.image.url)

    class Meta:
        verbose_name = u'Фотография'
        verbose_name_plural = u'Фотографии'

    def delete(self, *args, **kwargs):
        storage, path = self.image.storage, self.image.path
        super(Photo, self).delete(*args, **kwargs)
        storage.delete(path)

    def add_to_gallery(self):
        gallery = Gallery.objects.get(title_slug='%s-gallery' % owner.username)
        gallery.objects.photos.add(self)

    def save(self, *args, **kwargs):
        if not self.pk:
            self.created = now()
        if not self.title:
            self.title = '_'.join(self.owner.pk,
                self.pk, self.image.filename)
        return super(Photo, self).save(*args, **kwargs)


class Category(models.Model):

    objects = managers.CategoryManager()

    parent = CachedForeignKey('self',
        null=True, blank=True,
        verbose_name=u'Предок')
    title = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=64)
    slug = AutoSlugField(u'Слуг', max_length=64, populate_from='title',
                         unique_with=('title'),
                         slugify=lambda value: value.replace(' ','-'))
    # fake recipe photo
    photo = CachedForeignKey(Photo, verbose_name=u'Фотография',
        null=True, blank=True)
    path = models.CharField(max_length=255, editable=False, unique=True)
    description = models.TextField(u'Описание', blank=True)

    class Meta:
        verbose_name = u'Категория'
        verbose_name_plural = u'Категории'
        ordering = ('path',)

    def __unicode__(self):
        return self.title

    def get_root_ancestor(self):
        if self.parent is not None:
            return self.parent.get_root_ancestor()
        return self

    @property
    def chained_title(self):
        if self.parent:
            return "%s / %s" % (self.parent.chained_title, self.title)
        return self.title

    def get_absolute_url(self):
        return reverse('yummy:category_detail', args=(self.path,))

    @property
    def is_root_category(self):
        return self.parent is None

    def is_ancestor_of(self, category=None):
        if category is None or category.is_root_category:
            return False
        if category.parent == self:
            return True
        return self.is_ancestor_of(category.parent)

    def get_children(self, recache=False):
        cache_key = "%s_direct_descendants" % self.pk
        cached_cats = cache.get(cache_key)
        if cached_cats is None or recache:
            cached_cats = list(self.__class__.objects.filter(parent=self))
            cache.set(cache_key, cached_cats)
        return cached_cats

    def get_descendants(self, recache=False):
        cats = []
        for child_category in self.get_children(recache):
            cats += [child_category]
            cats += child_category.get_descendants()
        return cats

    @property
    def level(self):
        return len(self.path.split('/'))

    def path_is_unique(self):
        if self.parent:
            path = '%s/%s' % (self.parent.path, self.slug)
        else:
            path = self.slug

        qs = self.__class__.objects.filter(path=path)
        if self.pk:
            qs = qs.exclude(pk=self.pk)
        return not bool(qs.count())

    def clean(self):
        if self == self.parent:
            raise ValidationError(u'Дочерняя категория должна отличаться от родительской')

        if self.is_ancestor_of(self.parent):
            raise ValidationError(u'Родителская категория не может быть потомком этой категории')

        if not self.path_is_unique():
            raise ValidationError(u'Указанный путь не уникален, изменить название категории или слуг')

    def save(self, **kwargs):
        """Override save() to construct path based on the category's parent."""
        old_path = self.path
        # if not self.slug:
            # self.slug = slugify(self.title)

        if self.parent:
            if self == self.parent or self.is_ancestor_of(self.parent):
                raise IntegrityError(u'Структура категорий нарушена. Проверьте родительскую категорию')
            self.path = '%s/%s' % (self.parent.path, self.slug)
        else:
            self.path = self.slug

        super(Category, self).save(**kwargs)

        if old_path != self.path:
            if self.parent:
                self.parent.get_descendants(recache=True)

            # update descendants' path
            for cat in self.get_descendants():
                cat.save(force_update=True)

    '''
    @property
    def photo_hierarchic(self):
        if self.photo:
            return self.photo
        if self.parent:
            return self.parent.photo_hierarchic
        return ""
    '''

    def get_recipes_count(self, recache=False):
        cache_key = '%s_subcats_recipes_count' % self.pk
        recipes_count = cache.get(cache_key)
        if recipes_count is None or recache:
            recipes_count = Recipe.objects.filter(is_public=True, is_approved=True, category=self).count()
            children = Category.objects.filter(parent=self)
            for one in children:
                recipes_count += one.get_recipes_count()
            cache.set(cache_key, recipes_count)

        return recipes_count


class UnitConversion(models.Model):

    from_unit = models.PositiveSmallIntegerField(choices=conf.UNIT_CHOICES, verbose_name=u'Из')
    to_unit = models.PositiveSmallIntegerField(choices=conf.UNIT_CHOICES, verbose_name=u'В')
    ratio = models.DecimalField(u'Соотношение', max_digits=10, decimal_places=5)

    def __unicode__(self):
        return u"1%s = %s%s" % (self.from_unit, self.ratio, self.to_unit)

    class Meta:
        unique_together = (('from_unit', 'to_unit',),)
        verbose_name = u'Конвертер единиц измерения'
        verbose_name_plural = u'Конвертеры единиц измерения'


class ShoppingList(models.Model):

    owner = CachedForeignKey(User, verbose_name=u'Калинар')
    title = models.CharField(u'Название', max_length=155)
    note = models.TextField(u"Заметка", blank=True)

    def __unicode__(self):
        return u"%s: %s" % (u"Список покупок", self.title)

    class Meta:
        verbose_name = u"Список покупок"
        verbose_name_plural = u"Списки покупок"


class ShoppingListItem(models.Model):

    shopping_list = CachedForeignKey(ShoppingList)
    ingredient = CachedForeignKey(Ingredient, verbose_name=u'Ингредиент')
    amount = models.DecimalField(u'Количество', max_digits=5, decimal_places=2, null=True, blank=True)
    unit = models.PositiveSmallIntegerField(u'Единица измерения', choices=conf.UNIT_CHOICES, null=True, blank=True)
    note = models.CharField(u'Заметка', max_length=255, blank=True)

    def __unicode__(self):
        return u"%s %s %s" % (self.ingredient, u'в списке покупок', self.shopping_list.title)

    class Meta:
        unique_together = (('shopping_list', 'ingredient'),)
        verbose_name = u'Запись в списке покупок'
        verbose_name_plural = u'Записи в списке покупок'


class CookBook(models.Model):

    owner = CachedForeignKey(User, verbose_name=u'Калинар')
    title = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=128)
    slug = AutoSlugField(u'Слуг', max_length=128, populate_from='title',
                         unique_with=('title', 'owner'),
                         slugify=lambda value: value.replace(' ','-'))
    is_public = models.BooleanField(u"Публичный", default=True)
    recipes = models.ManyToManyField('Recipe', verbose_name=u'Рецепт', through='CookBookRecipe')
    is_default = models.BooleanField(u"Килинариная книга по-умолчанию", default=False)

    objects = managers.CookBookManager()

    def __unicode__(self):
        return u"Кулинарная книга %s: %s" % (self.owner, self.title)

    class Meta:
        unique_together = (('owner', 'slug'),)
        verbose_name = u'Килинариная книга'
        verbose_name_plural = u'Килинариные книги'

    '''def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        return super(CookBook, self).save(*args, **kwargs)'''

    def get_recipes_count(self, recache=False):
        cache_key = "%s_get_cookbook_recipes" % self.pk
        recipes_count = cache.get(cache_key)
        if recipes_count is None or recache:
            recipes_count = CookBookRecipe.objects.filter(cookbook=self).count()
            cache.set(cache_key, recipes_count)
        return recipes_count

    def get_top_photo(self):
        recipes = self.recipes.all().order_by('id')[:1]
        if not recipes:
            return ""
        return recipes[0].get_top_photo()

    # FIXME: возможно неоднозначное определение owner.username ?????
    def get_absolute_url(self):
        owner = self.owner
        return reverse('yummy:cookbook_detail', 
            # args=(slugify(owner.username), owner.pk, self.slug))
            args=(owner.pk, self.slug))


class WeekMenu(models.Model):

    day = models.IntegerField(u"День недели", choices=conf.WEEK_DAYS, unique=True)
    dinner = CachedForeignKey('Recipe', blank=True, null=True,
                verbose_name=u'Ужин', related_name="menu_dinner")
    breakfast = CachedForeignKey('Recipe', blank=True, null=True,
                verbose_name=u'Завтрак', related_name="menu_breakfast")
    lunch_soup = CachedForeignKey('Recipe', blank=True, null=True,
                verbose_name=u'Первое', related_name="menu_lunch_soup")
    lunch_meal = CachedForeignKey('Recipe', blank=True, null=True,
                verbose_name=u'Горячее', related_name="menu_lunch_meal")
    dessert = CachedForeignKey('Recipe', blank=True, null=True,
                verbose_name=u'Десерт', related_name="menu_dessert")
    even_week = models.BooleanField(u"Меню на неделю", default=False,
        choices=(
            (True, u"Четная"),
            (False, u"Нечетная"),
        ),
        help_text=u"Выберите меню для нечетной или нечетной недели. Неделя %s." % \
                        (u"нечетная" if date.isocalendar(date.today())[1] % 2 else u"четная"))

    objects = managers.WeekMenuManager()

    class Meta:
        unique_together = (('day', 'even_week'),)
        verbose_name = u'Меню дня'
        verbose_name_plural = u'Меню на неделю'

    def __unicode__(self):
        return u"Меню на %s неделю" % u"четную" if self.even_week else u'нечетную'


### <<<---RECIPE
class Recipe(models.Model):

    objects = managers.RecipeManager()

    title = models.CharField(u'Название', max_length=128)
    # slug = models.SlugField(u'Слуг', max_length=64, unique=True)
    slug = AutoSlugField(u'Слуг', max_length=64, populate_from='title',
                         unique_with=('owner__id', 'title', 'created__month'),
                         slugify=lambda value: value.replace(' ','-'))
    category = CachedForeignKey(Category, verbose_name=u"Категория")

    description = models.TextField(u'Короткое описание', blank=True)
    # preparation = models.TextField(u'Приготовление')
    # hint = models.TextField(u'Подсказка', blank=True)
    top_photo = CachedForeignKey(Photo, verbose_name=u'Фотография рецепта',
        null=True, blank=True)

    # preparation = CachedForeignKey('PreparationInRecipe', verbose_name=u'Приготовление')
    targetgroup = models.ManyToManyField(TargetGroup, verbose_name=u'Подходит для', blank=True)
    cooking_type = CachedForeignKey(CookingType, verbose_name=u'Тип рецепта', blank=True, null=True)
    cuisines = models.ManyToManyField(Cuisine, verbose_name=u'Национальная кухня', blank=True)
    servings = models.PositiveSmallIntegerField(u'Количество порций', choices=getattr(settings, 'YUMMY_SERVINGS_CHOICES', None), blank=True, null=True)

    price = models.SmallIntegerField(u'Цена', choices=conf.PRICING_CHOICES, default=3, db_index=True, null=True, blank=True)
    difficulty = models.PositiveSmallIntegerField(u'Сложность приготовления', choices=conf.DIFFICULTY_CHOICES, default=3, db_index=True, null=True, blank=True)
    preparation_time = models.PositiveSmallIntegerField(u'Время приготовления в минутах', blank=True, null=True)
    caloric_value = models.PositiveIntegerField(u'Количество калорий', blank=True, null=True)

    owner = CachedForeignKey(User, verbose_name=u'Кулинар')
    is_approved = models.BooleanField(u'Утвержден', default=False, db_index=True)
    is_public = models.BooleanField(u'Публичный', default=True)
    is_checked = models.BooleanField(u'Проверен', default=False)
    created = models.DateTimeField(editable=False)
    updated = models.DateTimeField(editable=False)

    def __unicode__(self):
        return self.title

    def save(self, **kwargs):
        self.updated = now()
        if not self.id:
            self.created = self.updated

        #if not self.slug:
        #    self.slug = slugify(self.title)
        super(Recipe, self).save(**kwargs)

        self.groupped_ingredients(recache=True)
        self.category.get_recipes_count(recache=True)

    class Meta:
        verbose_name = u'Рецепт'
        verbose_name_plural = u'Рецепты'
        permissions = (
            ("approve_recipe", u"Право утвердить рецепт"),
        )


    '''
    def get_photos(self, recache=False):
        cache_key = '%s_recipe_photos' % self.pk
        cached_photos = cache.get(cache_key)
        if cached_photos is None or recache:
            cached_photos = []
            qs = self.recipephoto_set.visible().select_related('photo').order_by('order')
            for one in qs:
                if one.photo.owner_id == self.owner.pk:
                    cached_photos.insert(0, one.photo)
                else:
                    cached_photos.append(one.photo)
            cache.set(cache_key, cached_photos)

        return cached_photos
    '''

    def get_preparation_photos(self, recache=False):
        cache_key = '%s_recipe_preparation_photos' % self.pk
        cached_photos = cache.get(cache_key)
        if cached_photos is None or recache:
            cached_photos = []
            qs = self.preparationinrecipe_set.select_related('photo').order_by('order')
            for one in qs:
                if one.photo.owner_id == self.owner.pk:
                    cached_photos.insert(0, one.photo)
                else:
                    cached_photos.append(one.photo)
            cache.set(cache_key, cached_photos)

        return cached_photos

    def get_top_photo(self):
        if self.top_photo:
            return self.top_photo
        else:
            return ""  # need return @No photo@
            # return self.category.photo_hierarchic

    def ingredients(self):
        cache_key = '%s_ingredients' % self.pk
        ingr = cache.get(cache_key)
        if ingr is None:
            ingr = IngredientInRecipe.objects.filter(recipe=self).select_related('ingredient').order_by('group__order', 'order')
        return ingr

    def preparation(self):
        cache_key = '%s_preparation' % self.pk
        prep = cache.get(cache_key)
        if prep is None:
            prep = PreparationInRecipe.objects.filter(recipe=self).order_by('order')
        return prep

    def groupped_ingredients(self, recache=False):
        """
        order items by group's priority
        if items are not in any group, set them into anonymous group \
            which has highest priority (lowest number)
        to keep priorities while listing, conversion to list is needed

        :param recache: force recache
        :type recache: bool
        :return: list of groups w/ items: (group, {prioriy:1, items:[]}
        :rtype: list
        """
        cache_key = '%s_groupped_ingredients' % self.pk
        groups = cache.get(cache_key)
        if groups is None or recache:
            qs = IngredientInRecipe.objects.filter(recipe=self).select_related('ingredient').order_by('group__order', 'order')

            tmp_groups = {}
            for one in qs:
                group_index = one.group.title if one.group else '__nogroup__'
                group_priority = one.group.order if one.group else 0
                tmp_groups.setdefault(group_index, dict(items=[], priority=group_priority))['items'].append(one)

            groups = sorted(tmp_groups.items(), key=lambda x: x[1].get('priority'))
            cache.set(cache_key, groups)
        return groups

    def get_absolute_url(self):
        return reverse('yummy:recipe_detail', 
            args=(self.category.path, self.slug, self.pk,))

'''
class RecipePhoto(models.Model):

    objects = managers.RecipePhotoManager()

    recipe = CachedForeignKey('Recipe', verbose_name=u'Рецепт')
    photo = CachedForeignKey('Photo', verbose_name=u'Фотография')
    is_visible = models.BooleanField(u'Видимость', default=True)
    is_checked = models.BooleanField(u'Проверено', default=False)
    order = models.PositiveSmallIntegerField(u'№', db_index=True, blank=True)

    def __unicode__(self):
        return u"%d %s" % (self.order, self.photo)

    class Meta:
        unique_together = (
            ('recipe', 'photo'),
            ('recipe', 'order'),
        )
        verbose_name = u'Фоторецепт'
        verbose_name_plural = u'Фоторецепты'

    def save(self, *args, **kwargs):
        if not self.order:
            order = RecipePhoto.objects.filter(recipe=self.recipe).values_list('order', flat=True).order_by("-order")
            self.order = order[0] + 1 if order else 1
        super(RecipePhoto, self).save(*args, **kwargs)

"""
    # Go to cache
    @classmethod
    def _bump_photos(cls, *args, **kwargs):
        recipe_id = kwargs.get('instance').recipe_id
        try:
            recipe = Recipe.objects.get(pk=recipe_id)
        except Recipe.DoesNotExist:
            pass
        else:
            recipe.get_photos(recache=True)
"""
'''

class PreparationInRecipe(models.Model):

    objects = managers.PreparationInRecipeManager()

    recipe = CachedForeignKey('Recipe', verbose_name=u'Рецепт')
    photo = CachedForeignKey('Photo',
        verbose_name=u'Фотография для этого шага приготовления')
    order = models.PositiveSmallIntegerField(u'№', db_index=True, blank=True)
    preparation = models.TextField(u'Приготовление')

    def __unicode__(self):
        return u"%d %s" % (self.order, self.preparation)

    class Meta:
        unique_together = (
            #('recipe', 'photo'),
            ('recipe', 'order'),
        )
        verbose_name = u'Этап приготовления'
        verbose_name_plural = u'Этапы приготовления'

    def save(self, *args, **kwargs):
        if not self.order:
            order = PreparationInRecipe.objects.filter(recipe=self.recipe).values_list('order', flat=True).order_by("-order")
            self.order = order[0] + 1 if order else 1
        super(PreparationInRecipe, self).save(*args, **kwargs)


class IngredientInRecipeGroup(models.Model):

    recipe = CachedForeignKey(Recipe, verbose_name=u'Рецепт')
    title = models.CharField(u'Название', max_length=128)
    description = models.TextField(u'Краткое описание', blank=True)
    order = models.PositiveSmallIntegerField(u'№', db_index=True, blank=True)

    def __unicode__(self):
        return u"%s %s" % (self.recipe, self.title)

    class Meta:
        verbose_name = u'Ингредиент в группе рецептов'
        verbose_name_plural = u'Ингредиенты в группе рецептов'

    def save(self, *args, **kwargs):
        if not self.order:
            self.order = IngredientInRecipeGroup.objects.filter(recipe=self.recipe).count() + 1
        super(IngredientInRecipeGroup, self).save(*args, **kwargs)


class IngredientInRecipe(models.Model):

    recipe = CachedForeignKey(Recipe, verbose_name=u'Рецепт')
    group = CachedForeignKey(IngredientInRecipeGroup, verbose_name=u'Группа ингредиентов', null=True, blank=True)
    ingredient = CachedForeignKey(Ingredient, verbose_name=u'Ингредиент')
    amount = models.DecimalField(u'Количество', max_digits=5, decimal_places=2, null=True, blank=True)
    unit = models.PositiveSmallIntegerField(u'Единица измерения', choices=conf.UNIT_CHOICES, null=True, blank=True)
    order = models.PositiveSmallIntegerField(u'№', db_index=True, blank=True)
    note = models.CharField(u'Заметка', max_length=255, blank=True)

    def __unicode__(self):
        return u"%s - %s" % (self.ingredient, self.recipe)

    class Meta:
        verbose_name = u'Ингредиент в рецепте'
        verbose_name_plural = u'Ингредиенты в рецепте'

    def save(self, *args, **kwargs):
        if not self.order:
            self.order = IngredientInRecipe.objects.filter(recipe=self.recipe).count() + 1
        super(IngredientInRecipe, self).save(*args, **kwargs)

    @property
    def inflect_unit(self):
        if self.unit is None or self.amount is None:
            return ""
        f = conf.DICT_UNITS[self.unit]
        i = int(self.amount)

        # if decimal amount is equal to int(amount) return
        if self.amount == i:
            return f(i)

        # else use 3th translation form
        num_parts = str(self.amount).split(".")
        num = self.amount if len(num_parts) == 1 else 5
        return f(num)
### RECIPE--->>>


class RecipeRecommendation(models.Model):

    objects = managers.RecipeRecommendationManager()

    day_from = models.DateField(u'Демонстрировать c (включительно)', 
        help_text=u'Рецепт будет отображаться с указанной даты.')
    day_to = models.DateField(u'Демонстрировать до (включительно)', 
        blank=True, null=True,
        help_text=u'Рецепт будет отображаться до указанной даты.')
    recipe = CachedForeignKey(Recipe, verbose_name=u'Рецепт')

    def __unicode__(self):
        return u"'%s', %s - %s" % (self.recipe, self.day_from, (self.day_to or u'бесконечно'))

    class Meta:
        verbose_name = u'Рекомендованый рецепт'
        verbose_name_plural = u'Рекомендованые рецепты'

    def clean(self):
        if not self.recipe.is_approved:
            raise ValidationError(u'Вы можете сохранить рекомендацию только для утвержденных рецептов')

        '''if not self.recipe.top_photo:
            raise ValidationError(u'Вы можете сохранить рекомендацию только для рецептов с фотографией')'''

        if self.day_to and self.day_to < self.day_from:
            raise ValidationError(u'Неверно указана граница дат')

    def save(self, *args, **kwargs):
        try:
            self.clean()
        except ValidationError, e:
            raise IntegrityError(e.messages)

        super(RecipeRecommendation, self).save(*args, **kwargs)


class CookBookRecipe(models.Model):

    cookbook = CachedForeignKey('CookBook', verbose_name=u'Калинарная книга')
    recipe = CachedForeignKey('Recipe', verbose_name=u'Рецепт')
    note = models.CharField(u"Заметка", max_length=255, blank=True)
    added = models.DateField(u"Дата создания")

    class Meta:
        unique_together = (
            ('cookbook', 'recipe'),
        )
        verbose_name = u"Рецепт в кулинароной книге"
        verbose_name = u"Рецепты в кулинароной книге"

    def save(self, *args, **kwargs):
        if not self.pk:
            self.added = date.today()

        ret_value = super(CookBookRecipe, self).save(*args, **kwargs)

        self.cookbook.get_recipes_count(recache=True)
        self.cookbook.__class__.objects.get_user_cookbook_items_for_recipe(self.cookbook.owner,
                                                                           self.recipe,
                                                                           recache=True)
        return ret_value

    def delete(self, *args, **kwargs):
        cookbook = self.cookbook
        recipe = self.recipe
        super(CookBookRecipe, self).delete(*args, **kwargs)
        cookbook.get_recipes_count(recache=True)
        cookbook.__class__.objects.get_user_cookbook_items_for_recipe(cookbook.owner,
                                                                      recipe,
                                                                      recache=True)




# models.signals.post_save.connect(RecipePhoto._bump_photos, sender=RecipePhoto)
# models.signals.post_delete.connect(RecipePhoto._bump_photos, sender=RecipePhoto)
